<?php
class ClsLTemplate
{
    private $template="";
    private $templateDirectory="";
    private $themePath="";
    private $objModule=null;
    private $forModule="";
    private $forAction="";
    private $module="";
    private $action="";
    private $isTemplate=true;
    private $arrTplVar=array();
    private $errorMessage="";
    public function __construct($module,$action)
    {
        $this->template=$template;
        $modulePath=ClsNaanalApplication::getAbsModulePath($module,$action);
        $this->templateDirectory=file_exists("themes/{$theme}/")?"themes/":NAANAL_PATH."themes/";
        $this->themePath="{$this->templateDirectory}{$this->theme}/";
        if(!file_exists($this->themePath))
        {
            $this->themePath=NAANAL_PATH."themes/default/";
        }
        $objRequest=ClsNaanalRequest::getInstance();
        $arrRequest=$objRequest->getAll();
        
        $this->module=$objRequest->getModule();
        $this->action=$objRequest->getAction();
        if($this->theme===false)
        {
            $this->isTemplate==false;
        }
        else
        {
            $this->isTemplate=isset($arrRequest["template"]) && $arrRequest["template"]=="no" ? false : true;
        }
        
        $this->arrTplVar["current_module"]=$this->module;
        $this->arrTplVar["current_action"]=$this->action;
    }
    public function setErrorMessage($errorMessage)
    {
        $this->errorMessage=$errorMessage;
    }
    public function setForModule($forModule)
    {
        $this->forModule=$forModule;
    }
    public function setForAction($forAction)
    {
        $this->forAction=$forAction;
    }
    public function setModuleObject(&$objModule)
    {
        $this->objModule=$objModule;
    }
    public function setTemplateVariable($variable,$data)
    {
        $this->arrTplVar[$variable]=$data;
    }
    private function validateFile($tplPath)
    {
        if(!empty($this->arrTplVar)) extract($this->arrTplVar);
        
        $arrToken=token_get_all(file_get_contents($tplPath));
        $arrAllowedToken=array(311,367,316,370,315,369,T_VARIABLE);      
        $naanal_error=errMsg();
        foreach($arrToken as $ind=>$data)
        {
            $isAllowed=false;
            $isVariableError=false;
            $isFunctionError=false;
            if(!isset($data[2]) || in_array($data[0], $arrAllowedToken))
            {
                if($data[0]===T_VARIABLE)
                {
                    if(isset($this->arrConfigVar["template_variables"]) && in_array(substr($data[1],1), $this->arrConfigVar["template_variables"]))
                    {
                        $isAllowed=true;
                    }
                    else if($data[1]=='$theme_web_path' ||  $data[1]=='$theme_file_path' ||  $data[1]=='$form' || $data[1]=='$module' || $data[1]=='$action' || $data[1]=='$message' || $data[1]=='$formodule' || $data[1]=='$foraction' || $data[1]=='$naanal_error')
                    {
                        $isAllowed=true;
                    }
                    else
                    {
                        $isVariableError=true;
                    }
                }
                else if($data[0]===T_FUNCTION)
                {
                    $isFunctionError=true;
                }
                else
                {
                    $isAllowed=true;
                }
            }
            if($isVariableError)
            {
                $definedVar=$data[1];
                if($definedVar=='$_REQUEST' || $definedVar=='$_POST' || $definedVar=='$_GET' || $definedVar=='$_SESSION')
                {
                    $help="Usage of Super Globals such as \$_REQUEST, \$_POST, \$_GET and \$_SESSION are strictly restricted inside template";
                }
                else
                {
                    $definedVar=  substr($definedVar, 1);
                    $help="Variable other than defined in {$this->module} module's config.php is not allowed. If you need this variable define it in {$this->module} module's config.php. Ex.\$template_variables[]='{$definedVar}'";
                }
                traceDirect("File: {$tplPath}, Line No.: {$data[2]}, Variable '{$data[1]}' not allowed inside template. ".$help);
            }
            else if($isFunctionError)
            {
                die("File: {$tplPath}, Line No.: {$data[2]}, Function '{$data[1]}' not allowed inside template. ");
            }
        }
    }
    private function &processTemplate($page,$template,$arrTplVar=null,$mode=false)
    {
        $tplPath="";
        ob_start();
        if($page=="show_trace")
        {
            $tplPath=NAANAL_PATH."phptrace/trace.html";
        }
        else if($mode!==false && file_exists($this->modulePath.$mode.".php"))
        {
            $tplPath=$this->modulePath.$mode.".php";
        }
        else if(file_exists($this->modulePath.$template.".php"))
        {
            $tplPath=$this->modulePath.$template.".php";
        }
        else if(file_exists($this->modulePath.$page.".php"))
        {
                $tplPath=$this->modulePath.$page.".php";
        }
        $naanal_error=errMsg();
        if(!empty($tplPath))
        {
            if(!ClsNaanalApplication::$isApplicationHasError && $this->isModule())
            {
                $arrToken=token_get_all(file_get_contents($tplPath));
                $arrAllowedToken=array
                (
                    278,//"||"
                    282,//"!="
                    314,//constant part of string with variables
                    360,//"array"
                    374,//"{"
                    350,//empty
                    351,//empty
                    349,//isset
                    303,//else
                    322,//foreach
                    326,//as,
                    279,//"&&"
                    327,//switch
                    329,//case
                    332,//continue
                    297,//++
                    331,//break
                    335,//return
                    357,//=>
                    365,//"///"
                    368,//"<?php "
                    371,//' '
                    320,//for
                    296,//--
                    281,//===
                    358,//=>
                    283,301,305,307, 311,356,367,316,370,315,359,366,369,375,T_VARIABLE
                );    
                $arrAllowedVariable=isset($this->arrConfigVar["template_variables"])?$this->arrConfigVar["template_variables"]:array();
                $arrAllowedVariable[]="id";
                if(isset($this->arrConfigVar["fields"]) && !empty($this->arrConfigVar["fields"]))
                foreach($this->arrConfigVar["fields"] as $tmpfld=>$tmpdata) 
                {
                    $arrAllowedVariable[]=$tmpfld;
                }
                $isOtherError=false;
                $arrVariableError=array();
                if(IS_NAANAL_ADMIN===false) 
                {
                    $current_theme=$this->getConfigVar("theme")===true?ClsConfig::$theme:$this->getConfigVar("theme");
                    $arrTplVar["current_theme"]=$current_theme;
                    $arrAllowedVariable[]=$current_theme;

                    foreach($arrToken as $ind=>$data)
                    {
                        $isAllowed=false;
                        $isVariableError=false;
                        $isFunctionError=false;
                        if(!isset($data[2]) ||  in_array($data[0], $arrAllowedToken))
                        {
                            if($data[0]===T_VARIABLE)
                            {
                                if(in_array(substr($data[1],1), $arrAllowedVariable))
                                {
                                    $isAllowed=true;
                                }
                                else if($data[1]=='$module' || $data[1]=='$home_page' || $data[1]=='$rand' || $data[1]=='$action' || $data[1]=='$message' || $data[1]=='$formodule' || $data[1]=='$foraction' || $data[1]=='$naanal_error')
                                {
                                    $isAllowed=true;
                                }
                                else
                                {
                                    $isVariableError=true;
                                }
                            }
                            else if($data[0]===T_FUNCTION)
                            {
                                $isFunctionError=true;
                            }
                            else
                            {
                                $isAllowed=true;
                            }
                        }
                        else
                        {
                            $isOtherError=true;
                        }
                        if($isVariableError)
                        {
                            $definedVar=$data[1];
                            if($definedVar=='$_REQUEST' || $definedVar=='$_POST' || $definedVar=='$_GET' || $definedVar=='$_SESSION')
                            {
                                $help="Usage of Super Globals such as \$_REQUEST, \$_POST, \$_GET and \$_SESSION are strictly restricted inside template";
                                $definedVar=  substr($definedVar, 1);
                            }
                            else
                            {
                                $definedVar=  substr($definedVar, 1);
                                $help="Variable other than defined in $page module's config.php is not allowed.";
                            }
                            $arrVariableError[$definedVar]["line"][$data[2]]="";
                            $arrVariableError[$definedVar]["help"]=$help;
                            $arrVariableError[$definedVar]["file"]=$tplPath;
                            $arrVariableError[$definedVar]["page"]=$template;
                        }
                        else if($isFunctionError)
                        {
                            die("File: {$tplPath}, Page: {$template}, Line No.: {$data[2]}, Function '{$data[1]}' not allowed inside template. ");
                        }
                        else if($isOtherError)
                        {
                            die("File: {$tplPath}, Page: {$template}, Line No.: {$data[2]}, Element Type : {$data[0]} Element '{$data[1]}' not allowed inside template. ");
                        }
                    }
                }
                if(!empty($arrVariableError))
                {
                    $variMessage="";
                    $arrVarKey=  array_keys($arrVariableError);
                    foreach($arrVarKey as $vari)
                    {
                        $help=$arrVariableError[$vari]["help"];
                        $file=$arrVariableError[$vari]["file"];
                        $page=$arrVariableError[$vari]["page"];
                        $variMessage=$variMessage."<br />File: {$file}, Page: {$page}, Variable \${$vari} cannot be used inside template. <br />Help: ".$arrVariableError[$vari]["help"];
                        $variMessage=$variMessage."<br /> at Line No:";
                        $arrLine=  array_keys($arrVariableError[$vari]["line"]);
                        $variMessage=$variMessage.implode(", ",$arrLine);
                        $variMessage=$variMessage."<br />";
                    }
                    $variMessage=$variMessage."<br />Add the following in the module's config.php<br />";
                    foreach($arrVarKey as $vari)
                    {
                        if($vari=='_REQUEST' || $vari=='_GET' || $vari=='_POST' || $vari=='_SESSION' || $vari=='_SERVER') continue;
                        $variMessage=$variMessage."\$template_variables[]='{$vari}';<br />";
                    }
                    traceDirect($variMessage);
                }
            }
            echo $this->loadTemplateFile($tplPath, $arrTplVar);
            //include($tplPath);
        }
        else if($mode=="list")
        {

        }
        else
        {
                echo "<center><h1>Page({$page}) or Page({$template}) Not Found</h1></center>";
        }
        $out=ob_get_clean();
        return $out;
    }
    private function &processListTemplate($arrTplVar)
    {
        $cpanel=getCurrentControlPanel();
        $listFile=false;
        $workplacePath=ClsNaanalApplication::__getWorkplacePath();
        if(file_exists("{$workplacePath}{$this->module}_list.php")) $listFile="{$workplacePath}{$this->module}_list.php";
        else if(file_exists($this->modulePath."list.php")) $listFile=$this->modulePath."list.php";
        if(!file_exists($this->modulePath."list_template.php"))
        {
            $out="<a href='{$this->homepage}?page={$this->module}'>Add New</a><br />";
        } 
        else
        {
            $out="";
        }
        
        /**
            * if database data exist and if the data set is not empty 
            */
        if(isset($arrTplVar["list"]) && !empty($arrTplVar["list"]))
        {
            $out=$out."
            <table class='list' border=1 cellpadding=5 cellspacing=5 id='tbl_list_".$this->module."'>";
            
            foreach($arrTplVar["list"] as $ind=>$form)
            {
                $arrListVar=array();
                foreach($arrTplVar as $var=>$data)
                {
                    if($var=="list") continue;
                    $arrListVar[$var]=$data;
                }
                if(is_object($form))
                {
                    $arrListVar["id"]=array("value"=>$form->get_id());
                    $arrListVar["home_page"]["value"]=$this->homepage;
                    $arrListVar["control_panel"]["value"]=$cpanel;
                    $arrListVar["rand"]["value"]=$this->rand;
                    $arrListVar["module"]["value"]=$this->module;
                    $arrListVar["action"]["value"]=$this->action;
                    $arrListVar["module_path"]["value"]=$this->modulePath;
                    foreach($this->arrConfigVar["fields"] as $tmpfld=>$tmpdata)
                    {
                        $tmpfldform="get_{$tmpfld}";
                        $arrListVar[$tmpfld]=array("value"=>$form->$tmpfldform());
                    }
                }
                else
                {
                    $arrListVar["id"]=array("value"=>$form["id"]);
                    $arrListVar["home_page"]["value"]=$this->homepage;
                    $arrListVar["control_panel"]["value"]=$cpanel;
                    $arrListVar["rand"]["value"]=$this->rand;
                    $arrListVar["module"]["value"]=$this->module;
                    $arrListVar["action"]["value"]=$this->action;
                    $arrListVar["module_path"]["value"]=$this->modulePath;
                    if(!empty($this->arrConfigVar["fields"]))
                    foreach($this->arrConfigVar["fields"] as $tmpfld=>$tmpdata)
                    {
                        $arrListVar[$tmpfld]=array("value"=>$form[$tmpfld]);
                    }
                }
                $out = $out.$this->processTemplate($this->module,$listFile,$arrListVar,$this->action);
            }
        }
        $out=$out."</table>";
        
        if(isset($this->arrConfigVar["list_has_header"]) && $this->arrConfigVar["list_has_header"])
        {
            if(isset($arrTplVar["list"]))
            {
                unset($arrTplVar["list"]);
            }
            extract($arrTplVar);
            ob_start();
            include($this->modulePath.$this->action."_header.php");
            $out = ob_get_clean().$out;//$out.$this->processTemplate($this->module,$this->action."_header",null,$this->action);
        }
        
        $pagination="";
        if(isset($arrTplVar["pagination"])) $pagination=$arrTplVar["pagination"];
        if(file_exists($this->modulePath."list_template.php"))
        {
            ob_start();
            include $this->modulePath."list_template.php";
            $out=  ob_get_clean();
        }
        return $out;
    }
    private function &renderTheme($tplPath,&$out)
    {
        if(!empty($this->arrTplVar)) extract($this->arrTplVar);
        $naanal_error=errMsg();
        $html_tag_head="<script type='text/javascript'>var URL_BASE_FILE_NAME='".URL_BASE_FILE_NAME."';</script>";
        
        $dir_handle=  opendir(NAANAL_PATH."js");
        while($file = readdir($dir_handle))
        {
            trace($file);
        }
        
        $arrScriptInclude=loadScriptFiles(false,false,false);
        $arrJSInclude=isset($arrScriptInclude["js"])?$arrScriptInclude["js"]:array();
        $arrCSSInclude=isset($arrScriptInclude["css"])?$arrScriptInclude["css"]:array();
        
        if(!empty($arrCSSInclude))
        {
            foreach($arrCSSInclude as $cssfile)
            {
                $html_tag_head=$html_tag_head."<link rel='stylesheet' href='{$cssfile}' type='text/css' />";
            }
        }
        if(file_exists("{$this->themePath}css/utils.css"))
        {
            $html_tag_head=$html_tag_head."<link rel='stylesheet' href='{$this->themePath}css/utils.css' type='text/css' />";
        }
        if(file_exists("{$this->themePath}css/{$this->theme}.css"))
        {
            $html_tag_head=$html_tag_head."<link rel='stylesheet' href='{$this->themePath}css/{$this->theme}.css' type='text/css' />";
        }
        if(file_exists("css/utils.css"))
        {
            $html_tag_head=$html_tag_head."<link rel='stylesheet' href='css/utils.css' type='text/css' />";
        }
        if(file_exists("modules/{$this->module}/css/utils.css"))
        {
            $html_tag_head=$html_tag_head."<link rel='stylesheet' href='modules/{$this->module}/css/utils.css' type='text/css' />";
        }
        if(file_exists("modules/{$this->module}/css/{$this->module}.css"))
        {
            $html_tag_head=$html_tag_head."<link rel='stylesheet' href='modules/{$this->module}/css/{$this->module}.css' type='text/css' />";
        }
        if(file_exists("modules/{$this->module}/css/{$this->action}.css"))
        {
            $html_tag_head=$html_tag_head."<link rel='stylesheet' href='modules/{$this->module}/css/{$this->action}.css' type='text/css' />";
        }
        
        if(!empty($arrJSInclude))
        {
            foreach($arrJSInclude as $jsfile)
            {
                $html_tag_head=$html_tag_head."<script src='{$jsfile}' type='text/javascript'></script>";
            }
        }
        
        if(file_exists("{$this->themePath}js/utils.js"))
        {
            $html_tag_head=$html_tag_head."<script src='{$this->themePath}js/utils.js' type='text/javascript'></script>";
        }
        if(file_exists("{$this->themePath}js/{$this->theme}.js"))
        {
            $html_tag_head=$html_tag_head."<script src='{$this->themePath}js/{$this->theme}.js' type='text/javascript'></script>";
        }
        if(file_exists("js/utils.js"))
        {
            $html_tag_head=$html_tag_head."<script src='js/utils.js' type='text/javascript'></script>";
        }
        if(file_exists("modules/{$this->module}/js/utils.js"))
        {
            $html_tag_head=$html_tag_head."<script src='modules/{$this->module}/js/utils.js' type='text/javascript'></script>";
        }
        if(file_exists("modules/{$this->module}/js/{$this->module}.js"))
        {
            $html_tag_head=$html_tag_head."<script src='modules/{$this->module}/js/{$this->module}.js' type='text/javascript'></script>";
        }
        if(file_exists("modules/{$this->module}/js/{$this->action}.js"))
        {
            $html_tag_head=$html_tag_head."<script src='modules/{$this->module}/js/{$this->action}.js' type='text/javascript'></script>";
        }
        $theme_web_path=$this->themePath;
        $error=$this->errorMessage;
        ob_start();
        include($tplPath);
        $out=ob_get_clean();
        return $out;
    }
    public function &render($out)
    {
        $tplPath="";
        $page=!empty($this->forModule)?$this->forModule:$this->module;
        $action=!empty($this->forAction)?$this->forAction:$this->action; 
        if(!$this->isTemplate)
        {     
            return $out;
        }
        if($page=="home")
        {
            $objSession=ClsNaanalSession::getInstance();
            $isIntroStarted=$objSession->getPanelData("introStarted");
            if(!$isIntroStarted)
            {
                if(file_exists($this->themePath."intro.php"))
                {
                    $tplPath=$this->themePath."intro.php";
                }
            }
            if(empty($tplPath) && file_exists($this->themePath."home.php"))
            {
                $tplPath=$this->themePath."home.php";
            }
        }
        
        if(empty($tplPath) && file_exists($this->themePath."inner.php"))
        {
            $tplPath=$this->themePath."inner.php";
        }
        if(!empty($tplPath))
        {
            $out=$this->renderTheme($tplPath,$out);
        }
        return $out;
    }
    public static function &getInstance($module,$action)
    {
        static $arrTemplate=array();
        if(!isset($arrTemplate[$template]))
        {
            $arrTemplate[$template]=new ClsLTemplate($module,$action);
        }
        return $arrTemplate[$template];
    }
}
?>